package com.atguigu.tingshu.account.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.account.mapper.RechargeInfoMapper;
import com.atguigu.tingshu.account.mapper.UserAccountMapper;
import com.atguigu.tingshu.account.service.MqService;
import com.atguigu.tingshu.account.service.UserAccountService;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.model.account.RechargeInfo;
import com.atguigu.tingshu.model.account.UserAccount;
import com.atguigu.tingshu.order.client.OrderInfoFeignClient;
import com.atguigu.tingshu.vo.account.AccountLockResultVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.math.BigDecimal;

/**
 * @author codingyz
 * @Description
 * @date 2025/3/28 20:25
 * @Version 1.0
 */
@Service
@Slf4j
public class MqServiceImpl implements MqService {

    @Autowired
    private UserAccountMapper userAccountMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private UserAccountService userAccountService;
    @Autowired
    private RechargeInfoMapper rechargeInfoMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unlockAccount(String orderNo) {
        String userAccountKey = "user:account:amount" + orderNo;
        String lockKey = "user:account:amount:lock:retry" + orderNo;
        // 解锁用户账户锁定金额
        // 从redis获取锁定的数据
        String accountLockResultVoStr = redisTemplate.opsForValue().get(userAccountKey);
        if (!StringUtils.hasText(accountLockResultVoStr)) {
            log.error("已经被解锁,无需解锁");
            return;
        }
        AccountLockResultVo accountLockResultVo = JSONObject.parseObject(accountLockResultVoStr, AccountLockResultVo.class);
        Long userId = accountLockResultVo.getUserId();
        BigDecimal amount = accountLockResultVo.getAmount();
        // 解锁用户账户
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(lockKey, "1");
        if (aBoolean) {
            try {
                userAccountMapper.unlockAmount(userId, amount);
                // 解锁的记录存放到流水表中
                userAccountService.log("解锁" + accountLockResultVo.getContent(), userId, amount, orderNo, "1203-解锁");
                // 删除缓存中的锁定记录
                redisTemplate.delete(userAccountKey);
            } catch (Exception e) {
                log.error("解锁失败");
                throw new GuiguException(ResultCodeEnum.ACCOUNT_UNLOCK_ERROR);
            } finally {
                redisTemplate.delete(lockKey);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unlockAccountMinus(String orderNo) {
        String userAccountKey = "user:account:amount" + orderNo;
        String lockKey = "user:account:amount:lock:minus:retry" + orderNo;
        // 解锁用户账户锁定金额
        // 从redis获取锁定的数据
        String accountLockResultVoStr = redisTemplate.opsForValue().get(userAccountKey);
        if (!StringUtils.hasText(accountLockResultVoStr)) {
            return;
        }
        AccountLockResultVo accountLockResultVo = JSONObject.parseObject(accountLockResultVoStr, AccountLockResultVo.class);
        Long userId = accountLockResultVo.getUserId();
        BigDecimal amount = accountLockResultVo.getAmount();
        // 解锁用户账户
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(lockKey, "1");
        if (aBoolean) {
            try {
                userAccountMapper.minus(userId, amount);
                // 解锁的记录存放到流水表中
                userAccountService.log("消费" + accountLockResultVo.getContent(), userId, amount, orderNo, "1204-消费");
                // 删除缓存中的锁定记录
                redisTemplate.delete(userAccountKey);
            } catch (Exception e) {
                log.error("消费失败");
                throw new GuiguException(201, "消费失败");
            } finally {
                redisTemplate.delete(lockKey);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void userAccountRecharge(String orderNo) {
        // 微信支付成功 修改订单状态
        int count = rechargeInfoMapper.updateRechargeStatus(orderNo);
        log.info("修改订单状态:{}", count == 0 ? "失败" : "成功");
        // 增加用户零钱
        RechargeInfo rechargeInfo = rechargeInfoMapper.selectOne(new LambdaQueryWrapper<RechargeInfo>().eq(RechargeInfo::getOrderNo, orderNo));
        Long userId = rechargeInfo.getUserId();
        int rows = userAccountMapper.addAmount(userId, rechargeInfo.getRechargeAmount());
        log.info("修改用户余额:{}", rows == 0 ? "失败" : "成功");
        // 记录用户流水
        userAccountService.log("充值" + rechargeInfo.getRechargeAmount(), userId, rechargeInfo.getRechargeAmount(), orderNo, "1201-充值");
    }
}
